package com.zzr.demo.excel.service.impl;

import com.zzr.demo.excel.Annotation.ExcelAnnotation;
import com.zzr.demo.excel.service.IExcelService;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.boot.web.servlet.server.Session;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;


public class ExcelServiceImpl implements IExcelService {

    /**
     * 导出excel表
     * @param response
     * @param name
     * @throws IOException
     */
    @Override
    public <T>void exportExel(HttpServletResponse response, List<T> list, Class<T> clazz, String name) {

        try {
            HSSFWorkbook wb = generateExelFile(list, clazz,name);

            //到这里，excel就已经生成了，然后就需要通过流来写出去
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            //将excel写入流
            wb.write(byteArrayOutputStream);
            //设置文件标题
            String outFile = name + ".xls";
            //设置返回的文件类型
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            //对文件编码
            outFile = response.encodeURL(new String(outFile.getBytes("gb2312"), "iso8859-1"));
            //使用Servlet实现文件下载的时候，避免浏览器自动打开文件
            response.addHeader("Content-Disposition", "attachment;filename=" + outFile);
            //设置文件大小
            response.setContentLength(byteArrayOutputStream.size());
            //创建Cookie并添加到response中
            Cookie cookie = new Cookie("fileDownload", "true");
            cookie.setPath("/");
            response.addCookie(cookie);
            //将流写进response输出流中
            ServletOutputStream outputstream = response.getOutputStream();
            byteArrayOutputStream.writeTo(outputstream);

            byteArrayOutputStream.close();
            outputstream.flush();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成Excel文件
     * @param list
     * @return
     */
    public <T> HSSFWorkbook generateExelFile(List<T> list,Class<T> clazz,String sheetName) throws IllegalAccessException {
        //解析注解
        Field[] fields = clazz.getDeclaredFields();
        HashMap<Integer, Field> fieldMap = new HashMap<>();
        for (Field field : fields) {
            boolean annotationPresent = field.isAnnotationPresent(ExcelAnnotation.class);
            if (annotationPresent){
                ExcelAnnotation excelAnnotation = field.getAnnotation(ExcelAnnotation.class);
                fieldMap.put(excelAnnotation.index(),field);
            }
        }

        //生成exel文件
        //创建工作薄
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建工作表
        HSSFSheet sheet = wb.createSheet();
        sheet.createFreezePane(0, 1, 0, 1);
        wb.setSheetName(0, sheetName);

        /*//默认宽高
        sheet.setDefaultColumnWidth((short) 20);
        sheet.setDefaultRowHeight((short) 2000);*/

        //创建样式和字体
        HSSFCellStyle curStyle = wb.createCellStyle();
        HSSFFont curFont = wb.createFont();
        Font font = wb.getFontAt((short) 0);
        CellStyle style = wb.createCellStyle();
        font.setCharSet(HSSFFont.DEFAULT_CHARSET);
        //更改默认字体大小
        font.setFontHeightInPoints((short) 12);
        font.setFontName("宋体");
        style.setFont(font);

        //创建行列
        HSSFRow nRow = sheet.createRow(0);
        HSSFCell nCell = nRow.createCell(0);
        //设置列的样式（具体实现在后面......）
        nCell.setCellStyle(mainTitleStyle(curStyle, curFont));
        //控制行号列号
        int rowNo = 0;

        //设置标题到第一行的列中
        nRow = sheet.createRow(rowNo++);
        for (int i = 0; i < fieldMap.size(); i++) {
            nCell = nRow.createCell(i);
            nCell.setCellValue(fieldMap.get(i).getAnnotation(ExcelAnnotation.class).value());
            nCell.setCellStyle(textStyle(curStyle, curFont));
        }
        //创建样式和字体
        curStyle = wb.createCellStyle();
        curFont = wb.createFont();


        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();

        //封装exel 表体
        for (int i = 0; i < list.size(); i++) {
            T dto = list.get(i);
            nRow = sheet.createRow(rowNo++);
            //HSSFCell nCell;
            int colNo = 0;//控制列号
            //第一列
            for (int j=0;j<fieldMap.size();j++){
                Field field=fieldMap.get(j);
                field.setAccessible(true);
                nCell = nRow.createCell(colNo++);
                nCell.setCellValue(field.get(dto).toString());
                nCell.setCellStyle(textStyle(curStyle, curFont));
            }
        }
        return wb;
    }

    /**
     * 表格内容样式
     *
     * @param curStyle
     * @param curFont
     * @return
     */
    public HSSFCellStyle textStyle(HSSFCellStyle curStyle, HSSFFont curFont) {
        curStyle.setAlignment(CellStyle.ALIGN_CENTER);    //水平居中
        curStyle.setWrapText(true); // 自动换行
        curFont.setFontName("宋体");//字体
        curFont.setFontHeightInPoints((short) 10);//字体大小
        curStyle.setFont(curFont); // 绑定关系
        return curStyle;
    }

    /**
     * 表格标题样式
     *
     * @param curStyle
     * @param curFont
     * @return
     */
    public HSSFCellStyle mainTitleStyle(HSSFCellStyle curStyle, HSSFFont curFont) {
        curStyle.setAlignment(CellStyle.ALIGN_GENERAL);    //水平居中
        curFont.setFontHeightInPoints((short) 16);//字体大小
        curStyle.setFont(curFont); // 绑定关系
        return curStyle;
    }
}
